<html>
   <head>
      <script src="../../../Grid/GridE.js"> </script>
   </head>
   <body class="Example">
      <style>
         /* Examples shared styles */
         .Example h1,.Example h2,.Example ul,.Example .Desc,.Example .Path,.Example .Xml { max-height:999999px; }
         .Example h1 { font:30px Arial; padding:5px 0px 5px 0px; margin:0px; text-align:center; }
         .Example h2 { font:15px Arial; padding:0px; margin:0px 0px 10px 0px; text-align:center; color:#757575; }
         .Example h3,.Example h4 { display:inline-block; font:bold 15px/17px Arial; padding:0px 5px 0px 5px; border-radius:2px; margin:2px; color:#333; }
         .Example h3 { background:#EE9; border:1px solid #DD8; }
         .Example h4 { background:#BDE; border:1px solid #ACD; }
         .Example a { text-decoration:underline; }      
         .Example li { padding-bottom:8px; }
         .Example ul { margin:6px 0px 0px 0px; font:13px/16px Arial; }    
         .Example > ul { margin-left:0px; padding-left:15px; clear:both; }
         .Example ul b { color:#0585B9; }
         .Example .Desc { margin:0px 5px 10px 5px; padding:10px; border:1px solid #dfdfdf; font:14px/17px Arial; }
         .Example .Desc b { color:#0585B9; }
         .Example .Path { font:normal 12px Arial; color:#0585B9; }
         .Example .Path b { color:#D73938; }
         .Example .Path u { text-decoration:none; color:black; font-weight:bold; padding:0px 2px 0px 2px; }
         .Example .Path i { color:black; font-style:normal; font-weight:bold; }
         .Example .Xml { margin-bottom:6px; font:11px/14px Arial; color:#757575; }
         .Example .Border { margin:0px 5px 0px 5px; }
         .Example .Main { }
          @media (max-height:800px) { 
            .Example .Desc { font-size:13px; line-height:15px; margin:0px 5px 5px 5px; padding:3px 5px; } 
            .Example .Border { margin-bottom:0px; }
            .Example h1 { font:20px Arial; padding:0px; }
            .Example h2 { font:12px Arial; }
            }

          /* Examples specific styles */
         .GSGanttNbspOut, .GWGanttNbspOut, .GMGanttNbspOut, .GTGanttNbspOut, .GBGanttNbspOut { background-color: rgba(230,255,255,0.5); }
         .PA, .GSGanttPAIn, .GWGanttPAIn, .GMGanttPAIn, .GTGanttPAIn, .GBGanttPAIn { background-color: #4472C4; color: white; }
         .PB, .GSGanttPBIn, .GWGanttPBIn, .GMGanttPBIn, .GTGanttPBIn, .GBGanttPBIn { background-color: #A6A6A6; color: white; }
         .PC, .GSGanttPCIn, .GWGanttPCIn, .GMGanttPCIn, .GTGanttPCIn, .GBGanttPCIn { background-color: #AA4470; color: white; }
         .GWDep .GWGanttBaseIn { padding-left: 5px; padding-right: 5px; }
         .GWGanttContainerLabel { padding-left:10px; }
         .Sum { background-color: #FFC000; color: white; }
         .SumErr { background-color: #FF0000; color: white; }
         .PA, .PB, .PC, .Sum, .SumErr { width: 46px; border: 1px solid #EEE; }
         .Vert { width: 60px; display: block; border-top: 0px none; margin: auto; text-align: left; padding-left: 5px; }
         .Horz { border-left: 0px none; display: inline-block; width: 45px; }
         .Sum.Horz, .SumErr.Horz { width: 50px; }
         .Day { background-color: #F4B183; border: 1px solid #EEE; }
         .Tip { width: 70px; display: inline-block; }

      </style>

      <script>

      // --- Called on double click ---
      Grids.OnDblClick = function EditText(G,row,col,x,y) {
         var A = G.GetGanttXY(row,col,x,y);
         if(!A||!A.Run) return false;
         if(A.RunContainer) Grids.EditTask(G); // Task name
         else if(A.RunType=="nbsp") Grids.EditResource(G); // Resource name
         else Grids.EditAction(G); // Action name
         return true;
         }

      // --- Custom action to edit container name = task ---
      Grids.EditTask = function(G,F,T) {
         var E = G.GetEvent(), A = G.GetGanttXY(E.Row,E.Col,E.X,E.Y); if(!A.Run) return false;
         var run = G.GetGanttRun(E.Row,E.Col), cont = A.RunContainer ? A.RunContainer : run[A.RunIndex][15]; if(!cont) return false;
         if(T) return true;
         var C = G.Cols.G.GanttRunContainersLabels, txt = C[cont]; if(!txt) txt = cont;
         G.Prompt("Enter the task name",txt,function(txt) {
            if(txt==null) return;
            if(C[cont]) {  // Existing task name
               C[cont] = txt; G.Recalculate(E.Row,E.Col,1);
               }
            else { // New task name
               var m = 0; for(var c in C) { var a = c.slice(1); if(m<a-0) m = a-0; }
               m = "O"+(m+1);
               for(var i=0;i<run.length;i++) if(run[i][15]&&run[i][15][0]==cont) run[i][15][0] = m;
               C[m] = txt; G.SetGanttRun(E.Row,E.Col,run);
               }
            });
         }

      // --- Custom action to edit joined boxes = resource ---
      Grids.EditResource = function(G,F,T) {
         var E = G.GetEvent(), A = G.GetGanttXY(E.Row,E.Col,E.X,E.Y), run = G.GetGanttRun(E.Row,E.Col); if(!A.Run||A.RunContainer) return false;
         if(T) return true;
         G.Prompt("Enter the resource text",run[A.RunIndex][12],function(txt) {
            if(txt==null) return;
            for(var i=A.RunIndex;i<run.length&&run[i][1]!="empty";i++) run[i][12] = txt;
            for(var i=A.RunIndex-1;i>=0&&run[i][1]!="empty";i--) run[i][12] = txt;
            G.SetGanttRun(E.Row,E.Col,run);
            });
         }

      // --- Custom action to edit box = action ---
      Grids.EditAction = function(G,F,T) {
         var E = G.GetEvent(), A = G.GetGanttXY(E.Row,E.Col,E.X,E.Y), run = G.GetGanttRun(E.Row,E.Col); if(!A.Run||A.RunContainer||run[A.RunIndex][1]!="box") return false;
         if(T) return true;
         G.Prompt("Enter the action text",run[A.RunIndex][2],function(txt) {
            if(txt==null) return;
            run[A.RunIndex][2]=  txt;
            G.SetGanttRun(E.Row,E.Col,run);
            });
         }

      // --- Generates the box content ---
      Grids.OnGetGanttRunText = function(G,row,col,run,index,text,width,left,max,cls) {
         if(G.Cols.G.GanttZoom=="Day quarters"||G.Cols.G.GanttZoom=="Days") return "";
         var ri = run[index]; if(ri[1]!="box"||ri[12]==null||text==null) return text;
         return ri[12].replace(/^[^\d]+/,"")+"."+text.replace(/^[^\d]+/,""); // resource.action
         }

      // --- Generates the container label ---
      Grids.OnGetGanttRunContainer = function(G,row,col,run,id,Rect,cls,first,last,type,txt){
         if(type==5) return [null,"    "+txt]; // Shifts the label only for export
         }

      // --- Generates the box tool tip ---
      Grids.OnGanttTip = function(G,row,col,tip,A,name) {
         if(name=="Run") {
            var run = G.GetGanttRun(row,col); if(!run) return tip;
            if(A.RunContainer) {
               for(var i=0,f=null,fd=null,l=null,ld=null,d=0;i<run.length;d+=run[i++][0]) if(run[i][15]==A.RunContainer) {
                  if(fd>d||fd==null) { fd = d; f = i; }
                  if(ld<d+run[i][0]||ld==null) { ld = d+run[i][0]; l = i; }
                  }
               var F=G.GetGanttRunBox(row,col,f),L=G.GetGanttRunBox(row,col,l);
               var op=G.Cols.G.GanttRunContainersLabels[A.RunContainer];
               return "<span class='Tip'>Project:</span>"+row.N+"<br><span class='Tip'>Task:</span>"+(op?op:A.RunContainer)+"<br><span class='Tip'>Start:</span>"+DateToString(F.Start)+"<br><span class='Tip'>End:</span>"+DateToString(L.End);
               }
            var ri = run[A.RunIndex]; if(ri[1]!="box") return tip;
            var op = G.Cols.G.GanttRunContainersLabels[ri[15][0]];
            return "<span class='Tip'>Project:</span>"+row.N+"<br><span class='Tip'>Task:</span>"+(op?op:ri[15][0])+"<br><span class='Tip'>Plant:</span>"+ri[3]+"<br><span class='Tip'>Resource:</span>"+ri[12]+"<br><span class='Tip'>Action:</span>"+ri[2]+"<br>"+tip;
            }
         if(name=="Dependency") {
            var f = G.Cols.G.GanttRunContainersLabels[A.DependencyFromBox], t = G.Cols.G.GanttRunContainersLabels[A.DependencyToBox];
            var diff = G.DiffGanttDate(A.DependencyStart,A.DependencyEnd);
            return "<span class='Tip'>From:</span>"+(f? f:A.DependencyFromBox)+"<br><span class='Tip'>To:</span>"+(t? t:A.DependencyToBox)+"<br><span class='Tip'>Start:</span>"+DateToString(A.DependencyStart)+"<br><span class='Tip'>End:</span>"+DateToString(A.DependencyEnd)+"<br><span class='Tip'>Lag:</span>"+(A.DependencyStart>A.DependencyEnd? "<span style='color:red;'>-"+diff+" hours</span>":diff+" hours");
            }
         return tip;
         }

      // --- Changes task and resource after box move ---
      Grids.OnGanttChanged = function(G,row,col,item,new1,new2,old1,old2,action) {
         if(item=="Run"&&action=="Move") {
            var run = G.GetGanttRun(row,col), op = null, res = null, chg = 0;
            if(run) for(var i=0;i<run.length;i++) {
               if(run[i][1]=="empty") { op = null; res = null; }
               else if(op==null) { op = run[i][15]; res = run[i][12]; }
               else {
                  if(run[i][15]!=op) { run[i][15] = op; chg = 1; }
                  if(run[i][12]!=res) { run[i][12] = res; chg = 1; }
                  }
               }
            if(chg) G.SetGanttRun(row,col,run);
            }
         G.RefreshGantt(5);
         }

      // --- Calculates custom Gantt headers ---
      var Headers = null, Sum = null; // Calculated Gantt headers by date
      Grids.OnCalculate = function(G) {
         Headers = { PA: {}, PB: {}, PC: {} }; Sum = {};
         for(var row=G.GetFirst();row;row=G.GetNext(row)) {
            var run = G.GetGanttRun(row,"G"); if(!run) continue;
            for(var i=0;i<run.length;i++) if(run[i][1]=="box") {
               var H = Headers[run[i][3]]; if(!H) continue;
               var box = G.GetGanttRunBox(row,"G",i), res = run[i][12];
               var d = G.RoundGanttDate(box.Start,1,null,"G","d",row);
               var e = d+24*60*60*1000;
               var U = Sum;
               if(!H[d]) H[d] = 0;
               if(!U[d]) U[d] = {};
               if(box.End<=e) { // Only one day
                  var a = G.DiffGanttDate(box.Start,box.End,"h");
                  H[d] += a; if(!U[d][res]) U[d][res] = 0; U[d][res] += a;
                  }
               else { // More days
                  var a = G.DiffGanttDate(box.Start,e,"h");
                  H[d] += a; if(!U[d][res]) U[d][res] = 0; U[d][res] += a;
                  while(e<box.End) {
                     d = e; e = d+24*60*60*1000; if(e>box.End) e = box.End;
                     if(!H[d]) H[d] = 0;
                     if(!U[d]) U[d] = {};
                     var a = G.DiffGanttDate(d,e,"h");
                     H[d] += a; if(!U[d][res]) U[d][res] = 0; U[d][res] += a;
                     }
                  }
               }
            }
         }

      // --- Returns custom Gantt headers for header 7 ---
      Grids.OnGetGanttHeader = function(G,val,index,date,nextdate,units,width,partial,col) {
         if(index!=7) return val;
         if(!Headers) Grids.OnCalculate(G);
         var cls = G.Cols.G.GanttZoom=="Days"||G.Cols.G.GanttZoom=="Day quarters" ? " Vert" : " Horz"
         var s = "<span class='Day"+cls+"'>Day "+Math.round((date-G.GetGanttDate(0))/3600000/24+1)+"</span>";
         var ut = 0;
         for(var n in Headers) {
            var cnt = Headers[n][date]; if(cnt) ut += cnt;
            s += "<span class='"+n+cls+"'>"+n+" "+(cnt? cnt:0)+"</span>";
            }
         var U = Sum[date]; if(!U) U = {};
         var sum = Object.keys(U).length*8;
         s += "<span class='"+(ut>sum?"SumErr":"Sum")+cls+"'>"+ut+(cls==" Horz"&&ut>=100? "/":" / ")+sum+"</span>";
         return s;
         }

      </script>
      <center class="Path"><script>document.write(location.href.replace(/(.*)(\/Examples\/|\/ExamplesGantt\/)([^\/]+)\/([^\/]+)\/([^\/]+)$/,"$2<b>$3</b>/<i>$4</i>/$5").replace(/([^<]|^)(\/|\.)/g,"$1<u>$2</u>"));</script></center>
      <h1>Joined boxes and containers</h1>
      <h2>A demonstration of Run bars joined on levels and Run containers with dependencies</h2>
      <div class="Desc">
         This examples shows projects summary. Every grid row is one project.<br />
         The green containers are individual <b>tasks</b>. Every <b>task</b> consists from <b>actions</b> (individual boxes).
         The <b>actions</b> are grouped (joined by nbsp boxes) according to the used <b>resource</b>.<br />
         The <b>action</b> is done in specific <b>plant</b>, the <b>plant</b> determines color of the action box, there are three <b>plants</b>: <b>PA</b> (blue), <b>PB</b> (gray), <b>PC</b> (purple).<br />
         The custom colored header shows summaries for given day in hours. PA/PB/PC show hours spent in the plant. The last box shows summary hours of all resources / all available hours for these resources.<br />
      </div>

      <div class="Desc">
         Drag Container or Box by <b>left</b> button to shift it.
         Drag Container by <b>right</b> button to create dependency.
         Drag Box by <b>right</b> button to move it to another container or row. Red arrows on drop mean to add to the resource, blue arrows add separately.<br />
         <b>Double</b> click to Container to edit the task. <b>Double</b> click to Box toe edit the action. <b>Double</b> click to nbsp Box (light green) to edit the resource.<br />
         <b>Ctrl</b> + click to Box or Dependency to delete it. <b>Right</b> click shows popup menu with actions for clicked item or space.<br />
      </div>
      <div class="Border">
         <div class="Main">
            <bdo Layout_Url="RunContainerDef.xml" Data_Url="RunContainerData.xml"></bdo>
         </div>
      </div>

      <!-- Google Analytics code run once for trial -->
      <script>
         var TGTrial = document.cookie.match(/TGTrialGantt\s*=\s*(\d+)/), TGIndex = 2048;
         if(!TGTrial||!(TGTrial[1]&TGIndex)) setTimeout(function(){
            var n = "RunTrialHtmlRun", d = (new Date((new Date).getTime()+31536000000)).toUTCString(); document.cookie = "TGTrialGantt="+((TGTrial?TGTrial[1]:0)|TGIndex)+";expires="+d;
            var u = document.cookie.match(/TGTrialUsed\s*=\s*(\d+)/); u = u ? u[1]-0+1 : 1; if(u<=11) document.cookie = "TGTrialUsed="+u+";path=/;expires="+d;
            var s = "<div style='width:0px;height:0px;overflow:hidden;'><iframe src='http"+(document.location.protocol=="https"?"s":"")+"://www.treegrid.com/Stat/GA.html?productName="
                 +(u==1||u==3||u==5||u==10?"UsedTrial"+u:n)+"' onload='var T=this;setTimeout(function(){document.body.removeChild(T.parentNode.parentNode);},1000);'/></div>";
            var F = document.createElement("div"); F.innerHTML = s; document.body.appendChild(F);
            },100);
      </script>
   </body>
</html>